// Copyright (c) Microsoft Corporation. 
// Licensed under the MIT license.

#include "ReductionSettingsCustomizations.h"
#include "SimplygonCustomPipelines.h"
#include "PropertyHandle.h"
#include "DetailLayoutBuilder.h"
#include "DetailCategoryBuilder.h"
#include "DetailWidgetRow.h"
#include "PropertyCustomizationHelpers.h"
#include "IDetailChildrenBuilder.h"
#include "IDetailPropertyRow.h"
#include "IDetailGroup.h"

#define LOCTEXT_NAMESPACE "ReductionSettingsCustomizations"

TSharedRef<SWidget> CreateReductionTargetWidget(const FText& ReductionTargetName, TSharedPtr<IPropertyHandle> ReductionTargetEnabled, TSharedPtr<IPropertyHandle> ReductionTarget)
{
	return
		SNew(SHorizontalBox)
		+ SHorizontalBox::Slot()
		.VAlign(VAlign_Center)
		[
			//Ratio
			SNew(SVerticalBox)
			+ SVerticalBox::Slot()
			.Padding(0.0f)
			.HAlign(HAlign_Center)
			.VAlign(VAlign_Center)
			.AutoHeight()
			[
				SNew(STextBlock)
				.Text(ReductionTargetName)
				.Font(IDetailLayoutBuilder::GetDetailFont())
			]
			+ SVerticalBox::Slot()
			.Padding(2.0f)
			.HAlign(HAlign_Center)
			.VAlign(VAlign_Center)
			.FillHeight(1.0f)
			[
				ReductionTargetEnabled->CreatePropertyValueWidget()
			]
			+ SVerticalBox::Slot()
			.Padding(2.0f)
			.HAlign(HAlign_Fill)
			.VAlign(VAlign_Center)
			.FillHeight(1.0)
			[
				ReductionTarget->CreatePropertyValueWidget()
			]
		];
}

TSharedRef<IPropertyTypeCustomization> FReductionSettingsPropertyCustomization::MakeInstance()
{
	return MakeShareable(new FReductionSettingsPropertyCustomization());
}

void FReductionSettingsPropertyCustomization::CustomizeHeader(TSharedRef<IPropertyHandle> StructPropertyHandle, FDetailWidgetRow& /*HeaderRow*/, IPropertyTypeCustomizationUtils& /*StructCustomizationUtils*/)
{

}

void FReductionSettingsPropertyCustomization::CustomizeChildren(TSharedRef<IPropertyHandle> StructPropertyHandle, IDetailChildrenBuilder& ChildBuilder, IPropertyTypeCustomizationUtils& /*StructCustomizationUtils*/)
{
	// Retrieve structure's child properties
	uint32 NumChildren;
	StructPropertyHandle->GetNumChildren(NumChildren);
	TMap<FName, TSharedPtr< IPropertyHandle > > PropertyHandles;
	for (uint32 ChildIndex = 0; ChildIndex < NumChildren; ++ChildIndex)
	{
		TSharedRef<IPropertyHandle> ChildHandle = StructPropertyHandle->GetChildHandle(ChildIndex).ToSharedRef();
		FProperty* Property = ChildHandle->GetProperty();
		if (Property)
		{
			const FName PropertyName = ChildHandle->GetProperty()->GetFName();
			PropertyHandles.Add(PropertyName, ChildHandle);
		}
	}

	//Hide settings
	PropertyHandles.FindAndRemoveChecked(GET_MEMBER_NAME_CHECKED(FReductionSettings, AllowDegenerateTexCoords));
	PropertyHandles.FindAndRemoveChecked(GET_MEMBER_NAME_CHECKED(FReductionSettings, UseSymmetryQuadRetriangulator));
	PropertyHandles.FindAndRemoveChecked(GET_MEMBER_NAME_CHECKED(FReductionSettings, SymmetryDetectionTolerance));
	PropertyHandles.FindAndRemoveChecked(GET_MEMBER_NAME_CHECKED(FReductionSettings, DataCreationPreferences));
	PropertyHandles.FindAndRemoveChecked(GET_MEMBER_NAME_CHECKED(FReductionSettings, OutwardMoveMultiplier));
	PropertyHandles.FindAndRemoveChecked(GET_MEMBER_NAME_CHECKED(FReductionSettings, InwardMoveMultiplier));
	PropertyHandles.FindAndRemoveChecked(GET_MEMBER_NAME_CHECKED(FReductionSettings, MaxEdgeLength));
	//PropertyHandles.FindAndRemoveChecked(GET_MEMBER_NAME_CHECKED(FReductionSettings, ProcessSelectionSetName));
	PropertyHandles.FindAndRemoveChecked(GET_MEMBER_NAME_CHECKED(FReductionSettings, MergeGeometries));
	PropertyHandles.FindAndRemoveChecked(GET_MEMBER_NAME_CHECKED(FReductionSettings, LockGeometricBorder));

	IDetailGroup& ReductionSettingsGroup = ChildBuilder.AddGroup(StructPropertyHandle->GetProperty()->GetFName(), StructPropertyHandle->GetPropertyDisplayName());
	IDetailGroup* ImportanceSettingsGroup = nullptr;

	FText ReductionTargetsText = FText::FromString(TEXT("Reduction Targets"));
	TSharedPtr<IPropertyHandle> TriRatioEnabled = PropertyHandles.FindAndRemoveChecked(GET_MEMBER_NAME_CHECKED(FReductionSettings, ReductionTargetTriangleRatioEnabled));
	TSharedPtr<IPropertyHandle> TriCountEnabled = PropertyHandles.FindAndRemoveChecked(GET_MEMBER_NAME_CHECKED(FReductionSettings, ReductionTargetTriangleCountEnabled));
	TSharedPtr<IPropertyHandle> MaxDeviationEnabled = PropertyHandles.FindAndRemoveChecked(GET_MEMBER_NAME_CHECKED(FReductionSettings, ReductionTargetMaxDeviationEnabled));
	TSharedPtr<IPropertyHandle> OnScreenSizeEnabled = PropertyHandles.FindAndRemoveChecked(GET_MEMBER_NAME_CHECKED(FReductionSettings, ReductionTargetOnScreenSizeEnabled));
	TSharedPtr<IPropertyHandle> TriRatio = PropertyHandles.FindAndRemoveChecked(GET_MEMBER_NAME_CHECKED(FReductionSettings, ReductionTargetTriangleRatio));
	TSharedPtr<IPropertyHandle> TriCount = PropertyHandles.FindAndRemoveChecked(GET_MEMBER_NAME_CHECKED(FReductionSettings, ReductionTargetTriangleCount));
	TSharedPtr<IPropertyHandle> MaxDeviation = PropertyHandles.FindAndRemoveChecked(GET_MEMBER_NAME_CHECKED(FReductionSettings, ReductionTargetMaxDeviation));
	TSharedPtr<IPropertyHandle> OnScreenSize = PropertyHandles.FindAndRemoveChecked(GET_MEMBER_NAME_CHECKED(FReductionSettings, ReductionTargetOnScreenSize));

	ReductionSettingsGroup.AddWidgetRow()
		.NameContent()
		[
			SNew(STextBlock)
			.Text(ReductionTargetsText)
			.Font(IDetailLayoutBuilder::GetDetailFont())
		]
		.ValueContent()
		.MinDesiredWidth(600)
		[
			SNew(SHorizontalBox)
			+ SHorizontalBox::Slot()
			.Padding(2.0f)
			.VAlign(VAlign_Center)
			.FillWidth(1.0f)
			[
				//Ratio
				CreateReductionTargetWidget(FText::FromString(TEXT("Triangle Ratio")), TriRatioEnabled, TriRatio)
			]
			+ SHorizontalBox::Slot()
			[
				SNew(SSpacer)
				//.Size(FVector2D(4.0f, 0.0))
			]
			+ SHorizontalBox::Slot()
			.Padding(2.0f)
			.VAlign(VAlign_Center)
			.FillWidth(1.0f)
			[
				CreateReductionTargetWidget(FText::FromString(TEXT("Triangle Count")), TriCountEnabled, TriCount)
			]
			+ SHorizontalBox::Slot()
			[
				SNew(SSpacer)
				.Size(FVector2D(4.0f, 0.0))
			]
			+ SHorizontalBox::Slot()
			.Padding(2.0f)
			.VAlign(VAlign_Center)
			.FillWidth(1.0f)
			[
				CreateReductionTargetWidget(FText::FromString(TEXT("Max Deviation")), MaxDeviationEnabled, MaxDeviation)
			]
			+ SHorizontalBox::Slot()
			[
				SNew(SSpacer)
				.Size(FVector2D(4.0f, 0.0))
			]
			+ SHorizontalBox::Slot()
			.Padding(2.0f)
			.VAlign(VAlign_Center)
			.FillWidth(1.0f)
			[
				CreateReductionTargetWidget(FText::FromString(TEXT("On Screen Size")), OnScreenSizeEnabled, OnScreenSize)
			]
		];

	for (auto Iter(PropertyHandles.CreateConstIterator()); Iter; ++Iter)
	{
		if (Iter.Key().ToString().Contains(TEXT("Importance")))
		{
			if (!ImportanceSettingsGroup)
				ImportanceSettingsGroup = &ReductionSettingsGroup.AddGroup("Importance", LOCTEXT("ImportanceSettings_DisplayName", "Importance"));

			ImportanceSettingsGroup->AddPropertyRow(Iter.Value().ToSharedRef());
		}
		else
		{
			ReductionSettingsGroup.AddPropertyRow(Iter.Value().ToSharedRef());
		}
	}
}

FReductionSettingsPropertyCustomization::FReductionSettingsPropertyCustomization()
{

}

#undef LOCTEXT_NAMESPACE
